package ua.nure.nguyen.blinov.chapter3.variantb;

/**
 * Реализовать методы сложения, вычитания, умножения и деления объектов (для тех
 * классов, объекты которых могут поддерживать арифметические действия). 1.
 * Определить класс Дробь (Рациональная Дробь) в виде пары чисел m и n. Объявить
 * и инициализировать массив из k дробей, ввести/вы­ ести значе- в ния для
 * массива дробей. Создать массив/список/множество объектов и пе- редать его в
 * метод, который изменяет каждый элемент массива с четным индексом путем
 * добавления следующего за ним элемента.
 * 
 * @author Viet Nguyen
 * 
 */
public class RationalNumber {
	private static final int DEFAULT_PRECISION = 10;

	private int m;
	private int n;
	private int ipart;
	private int[] fpart = new int[DEFAULT_PRECISION];
	private int sign;

	/**
	 * Allocates new RationalFraction object
	 * 
	 * @param m
	 *            The divisor
	 * @param n
	 *            The denominator
	 */
	public RationalNumber(int m, int n) {
		sign = m % n > 0 ? 1 : -1;
		int gcd = gcd(m, n);
		this.m = Math.abs(m / gcd) * sign;
		this.n = Math.abs(n / gcd);
		ipart = m / n;
		int tmp = Math.abs(m - ipart * n);
		for (int i = 0; i < fpart.length; i++) {
			tmp *= 10;
			fpart[i] = tmp / n;
			tmp -= fpart[i] * n;
		}
	}

	private int gcd(int a, int b) {
		int x = a;
		int y = b;
		while (y != 0) {
			int tmp = y;
			y = x % y;
			x = tmp;
		}
		return x;
	}

	/**
	 * Adds the RationalFraction object to this object
	 * 
	 * @param rf
	 *            The RationalFraction object
	 * @return The sum of the RationalFraction objects
	 */
	public RationalNumber add(RationalNumber rf) {
		return new RationalNumber(m * rf.n + rf.m * n, n * rf.n);
	}

	/**
	 * Subtracts this object by the RationalFraction object
	 * 
	 * @param rf
	 *            The RationalFraction object
	 * @return The difference of the RationalFraction objects
	 */
	public RationalNumber sub(RationalNumber rf) {
		return new RationalNumber(m * rf.n - rf.m * n, n * rf.n);
	}

	/**
	 * Multiplies this object by the RationalFraction object
	 * 
	 * @param rf
	 *            The RationalFraction object
	 * @return The product of the RationalFraction objects
	 */
	public RationalNumber mul(RationalNumber rf) {
		return new RationalNumber(m * rf.m, n * rf.n);
	}

	/**
	 * Divides this object by the RationalFraction object
	 * 
	 * @param rf
	 *            The RationalFraction object
	 * @return The quotient of the RationalFraction objects
	 */
	public RationalNumber div(RationalNumber rf) {
		return new RationalNumber(m * rf.n, rf.m * n);
	}

	public String toFraction() {
		return String.format("[%d/%d]", m, n);
	}

	public String toFloat() {
		StringBuilder result = new StringBuilder();
		int index = fpart.length;
		while (--index >= 0 && fpart[index] == 0) {
		}
		while (index >= 0) {
			result.append(fpart[index--]);
		}
		result.reverse();
		result.insert(0, String.format("%s%d.", sign > 0 ? "" : "-", ipart));
		return result.toString();
	}

	public String toString() {
		return toFraction() + "=" + toFloat();

	}

	/**
	 * Calls all the public methods of the solutions
	 * 
	 * @param args
	 */
	public static void main(String[] args) {
		RationalNumber rf = new RationalNumber(2, 9);
		RationalNumber rf2 = new RationalNumber(5, 14);
		System.out.println(rf.add(rf2).toString());
		System.out.println(rf.sub(rf2).toString());
		System.out.println(rf.mul(rf2).toString());
		System.out.println(rf.div(rf2).toString());
	}
}
